// reinit_nrf_dfu.c
#define nrf_dfu_init 	static old_nrf_dfu_init
#include "nrf_dfu.c"
#undef nrf_dfu_init

#include "../wdt/nrf_drv_wdt.h"
//////////////////////////////////////////////////////////////////////////
APP_TIMER_DEF(m_feed_wdt_timer_id);
static void feed_wdt_timer_handler(void * p_context)
{
    for (uint32_t i = 0; i < NRF_WDT_CHANNEL_NUMBER; i++)
    {
        nrf_wdt_reload_request_set((nrf_wdt_rr_register_t)(NRF_WDT_RR0 + i));
    }
}
static void timer_feed_wdt_init(void)
{
	if (nrf_wdt_started())
	{
	    ret_code_t err_code = app_timer_create(&m_feed_wdt_timer_id,
	                                        APP_TIMER_MODE_REPEATED,
	                                        feed_wdt_timer_handler);
	    APP_ERROR_CHECK(err_code);
	    
	    err_code = app_timer_start(m_feed_wdt_timer_id, 
	        APP_TIMER_TICKS(100), (void*)NULL);
	    APP_ERROR_CHECK(err_code);		
	}
}

uint32_t nrf_dfu_init()
{
    uint32_t ret_val = NRF_SUCCESS;
    uint32_t enter_bootloader_mode = 0;

    NRF_LOG_DEBUG("In real nrf_dfu_init");

    nrf_dfu_settings_init(false);

    // Initialize the clock and timers.
    clock_init();
    timers_init();

    // Continue ongoing DFU operations
    // Note that this part does not rely on SoftDevice interaction
    ret_val = nrf_dfu_continue(&enter_bootloader_mode);
    if (ret_val != NRF_SUCCESS)
    {
        NRF_LOG_DEBUG("Could not continue DFU operation: 0x%08x", ret_val);
        enter_bootloader_mode = 1;
    }

    // Check if there is a reason to enter DFU mode
    // besides the effect of the continuation
    if (nrf_dfu_enter_check())
    {
        NRF_LOG_DEBUG("Application sent bootloader request");
        enter_bootloader_mode = 1;
    }

    nrf_power_gpregret_set(0);

    if (enter_bootloader_mode != 0 || !nrf_dfu_app_is_valid())
    {
        scheduler_init();

		// Start the feed WDT timer.
		timer_feed_wdt_init();

        // Start the inactivity timer.
        ret_val = app_timer_start(nrf_dfu_inactivity_timeout_timer_id,
                                  APP_TIMER_TICKS(NRF_DFU_INACTIVITY_TIMEOUT_MS),
                                  NULL);

        if (ret_val != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Could not initialize inactivity timer");
            return ret_val;
        }

        // Initializing transports
        ret_val = nrf_dfu_transports_init();
        if (ret_val != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Could not initalize DFU transport: 0x%08x", ret_val);
            return ret_val;
        }

        (void)nrf_dfu_req_handler_init();

        // This function will never return
        NRF_LOG_DEBUG("Waiting for events");
        wait_for_event();
        NRF_LOG_DEBUG("After waiting for events");
    }

    // Erase additional data like peer data or advertisement name
    ret_val = nrf_dfu_settings_additional_erase();
    if (ret_val != NRF_SUCCESS)
    {
        return ret_val;
    }

    if (nrf_dfu_app_is_valid())
    {
        // Uninitialize the clock driver to prevent interfering with app.
        nrf_drv_clock_uninit();

        NRF_LOG_DEBUG("Jumping to: 0x%08x", MAIN_APPLICATION_START_ADDR);
        nrf_bootloader_app_start(MAIN_APPLICATION_START_ADDR);
    }

    // Should not be reached!
    NRF_LOG_INFO("After real nrf_dfu_init");
    return NRF_SUCCESS;
}

